<!DOCTYPE html>
<html lang="zh-cn">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">




<title>网站性能优化之CSS优化 | Miles`s</title>

<link rel="stylesheet" href="https://mada.gitee.io/notes//css/styles.css">

<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.2.0/css/all.css" 
integrity="sha384-hWVjflwFxL6sNzntih27bfxkr27PmbbK/iSvJ+a4+0owXq79v+lsFkW54bOGbiDQ" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.3.1.js" integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60=" crossorigin="anonymous"></script>


<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/zenburn.min.css" crossorigin="anonymous" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js" integrity="sha256-/BfiIkHlHoVihZdc6TFuj7MmJ0TWcWsMXkeDFwhi0zw=" crossorigin="anonymous"></script>
<script>hljs.initHighlightingOnLoad();</script>
<script src="https://mada.gitee.io/notes//js/highlight.js"></script>






<div class="container">
    <nav class="navbar level">
      <div class="navbar-brand">
          <a class="nav-item" href="https://mada.gitee.io/notes/"><h1 class="title is-3">Miles`s</h1></a>
      </div>           
      <div class="navbar-menu has-text-centered is-active">
          <div class="navbar-end is-centered">
              
           </div>
      </div>
    </nav>
  </div>
<div class="container">
  <h2 class="subtitle is-6">November 18, 2016</h2>
  <h1 class="subtitle is-size-4-mobile is-size-3-desktop">网站性能优化之CSS优化</h1>
  <div class="content">
    

<h1 id="关键呈现路径">关键呈现路径</h1>

<p>优化关键呈现路径对于改进网页性能至关重要：我们的目标是优先显示与用户要在网页上执行的主要操作有关的内容。</p>

<p>要提供快速的网络用户体验，浏览器需要做许多工作。大多数此类工作我们网络开发人员是看不到的：我们编写标记，屏幕上就会显示出漂亮的网页。但是，浏览器究竟是如何使用我们的HTML，CSS和JavaScrip在屏幕上呈现像素呢？</p>

<p>从收到HTML，CSS和JavaScript字节到对其进行必需的处理从而转变为呈现的像素的过程中还有许多中间步骤，优化性能骑士就是了解这些步骤中发生了什么－即<strong>关键呈现路径</strong></p>

<p><img src="../../images/css-performance/progressive-rendering.png" alt="progressive rendering" /></p>

<p>通过优化关键呈现路径，可以大大缩短首次呈现网页的时间。另外，了解关键呈现路径还可以为构建高性能交互式应用程序打下基础。</p>

<p>其实，处理交互式更新的过程是相同的，只是在连续循环中完成，理想情况下每秒可以处理60个侦！但是，我们还是按部就班来学校。</p>

<p>首先，开始介绍浏览器如何显示简单网页。</p>

<h1 id="构建对象模型">构建对象模型</h1>

<p>浏览器要在屏幕上渲染内容，需要构件DOM与CSSOM树。因此，我们需要确保HTML和CSS尽可能提供给浏览器。</p>

<p><strong>文档对象模型（DOM）</strong></p>

<pre><code class="language-html">&lt;html&gt;
  &lt;head&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width,initial-scale=1&quot;&gt;
    &lt;link href=&quot;style.css&quot; rel=&quot;stylesheet&quot;&gt;
    &lt;title&gt;Critical Path&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;p&gt;Hello &lt;span&gt;web performance&lt;/span&gt; students!&lt;/p&gt;
    &lt;div&gt;&lt;img src=&quot;awesome-photo.jpg&quot;&gt;&lt;/div&gt;
  &lt;/body&gt;
&lt;/html&gt;
</code></pre>

<p>通过上面的简单html网页，我们来看一下浏览器是如何处理的。</p>

<p><img src="../../images/css-performance/full-process.png" alt="full-process" /></p>

<ol>
<li><strong>转换：</strong>浏览器从磁盘或网络读取HTML的原始字节，然后根据指定的文件编码格式将其转换为相应字符。</li>
<li><strong>符号化：</strong>浏览器将字符串转换为<a href="http://www.w3.org/TR/html5/">W3C HTML5标准</a>指定的各种符号－比如&rdquo;&lsquo;、&rsquo;&ldquo;及其他［尖括号］内的字符串。每个符号都有特殊含义并一套规则。</li>
<li><strong>此法分析：</strong>发射的符号转换为对象，定义它们的属性与规则。</li>
<li><strong>DOM构建：</strong>最后，因为HTML标记定义不同标签间的相互关系（某些标签前套在其他标签中），所以创建的对象咋树状数据结构中互相链接，树状数据结构还捕获原始标记中定义的父子关系：比如HTML对象是body对象的父对象，body是paragraph对象的父对象等等。</li>
</ol>

<p><img src="../../images/css-performance/dom-tree.png" alt="dom tree" /></p>

<p>上述整个流程的最终输出是文档对象模型，即这个简单网页的DOM。浏览器使用它完成网页的所有后续处理。</p>

<p>每次浏览器处理HTML标记，都要完成上述各个步骤：将字节转换成为字符，确认符号，将符号转换为节点，然后构建DOM树，整个过程需要一些时间，处理大量HTML时更是如此。</p>

<p><img src="../../images/css-performance/dom-timeline.png" alt="dom timeline" /></p>

<p>如果文档很大，那么这个过程会更久。如果浏览器必须处理大量的HTML，这很可能成为你的瓶颈。</p>

<p>DOM树准备就绪后，DOM树还得捕获文档标记的属性及关系，但没有告诉我们元素在渲染时是什么样子，这是CSSOM的责任。</p>

<p><strong>CSS对象模型（CSSOM）</strong></p>

<p>浏览器在构建DOM时，在文档head部分解析道link标签，引用了外部的CSS样式表style.css.浏览器预见到它会需要这个资源来渲染页面，因此会立即发出一个该资源的请求，该请求返回如下：</p>

<pre><code class="language-css">body { font-size: 16px }
p { font-weight: bold }
span { color: red }
p span { display: none }
img { float: right }
</code></pre>

<p>与处理HTML非常相似的过程：</p>

<p><img src="../../images/css-performance/cssom-construction.png" alt="cssom construction" /></p>

<p><img src="../../images/css-performance/cssom-tree.png" alt="cssom tree" /></p>

<p><img src="../../images/css-performance/cssom-timeline.png" alt="cssom timeline" /></p>

<h1 id="渲染树构建-布局及绘制">渲染树构建、布局及绘制</h1>

<p>CSSOM和DOM树融合成一颗渲染树，随后计算每个可见元素的布局，并输出给绘制过程，在屏幕上渲染像素。优化这里的每一步对实现最佳渲染性能至关重要。</p>

<ul>
<li>DOM树与CSSOM树融合成渲染树。</li>
<li>渲染树只包括渲染页面需要的节点。</li>
<li>布局计算每个对象的精确位置及尺寸。</li>
<li>最后一步的绘制，输入确定的渲染树，在屏幕上渲染像素。</li>
</ul>

<p><img src="render-tree-construction.png" alt="render tree construction" /></p>

<p>为了构建渲染树，浏览器大致做了如下：</p>

<ol>
<li>从DOM树的根结点开始，遍历每个可见的节点。</li>
<li>某些节点完全不可见（如script，meta），因为它们不会在渲染结果中反映，所以会被忽略。</li>
<li>某些节点通过CSS隐藏，因此在渲染树中也会被忽略。</li>
<li>给每个接单找到相应匹配的CSSOM规则，并应用规则。</li>
<li>发射可见节点，连带其内容及计算的样式。</li>
</ol>

<p>有了渲染树，就能进入布局阶段。</p>

<p>为了弄清楚每个对象的准确尺寸和位置，浏览器从渲染树的根节点开始遍历，以计算页面上每个对象的几何信息。</p>

<pre><code class="language-html">
&lt;html&gt;
  &lt;head&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width,initial-scale=1&quot;&gt;
    &lt;title&gt;Critial Path: Hello world!&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;div style=&quot;width: 50%&quot;&gt;
      &lt;div style=&quot;width: 50%&quot;&gt;Hello world!&lt;/div&gt;
    &lt;/div&gt;
  &lt;/body&gt;
&lt;/html&gt;

</code></pre>

<p>上门页面body包含两个嵌套div：第一个div将节点尺寸设置为视口宽度的50%，第二个包含在父元素中的div宽度为父元素50%，即视口宽度的25%。</p>

<p>布局过程输出一个盒模型，它精确捕获每个元素在视口中的准确位置以及尺寸：所有相对度量单位都被转换为屏幕上的绝对像素位置，等等。</p>

<p>最后，既然我们知道了哪些节点可见，它们的计算样式以及几何信息，我们终于可以将这些信息传递给最后一个阶段，即把渲染树中的每个节点转换为屏幕上的实际像素－这一步通常称为<strong>绘制</strong>或者<strong>栅格化</strong>。</p>

<p><img src="layout-timeline.png" alt="layout timeline" /></p>

<ul>
<li>Timeline中，<strong>layout</strong>事件捕获渲染树中的构建及位置、尺寸的计算。</li>
<li>一旦布局完成，浏览器便发布<code>Paint Setup</code>与<code>Paint</code>事件，将渲染树转化为屏幕上的实际像素。</li>
</ul>

<p>渲染树的构建、布局与绘制所需的时间取决于文档大小、应用样式、当然，还有运行的设备：文档越大，浏览器要完成的工作就越多；样式越复杂，绘制需要的时间越长。</p>

<h1 id="阻塞渲染的css">阻塞渲染的CSS</h1>

<p>默认情况下，CSS被视为阻塞渲染的资源，这意味着CSSOM构建完成前，浏览器会暂停渲染任何已处理的内容，确保精简你的CSS，尽快传送它，并使用媒体类型与媒体查询来解除阻塞。</p>

<p>关键渲染路径要求我们兼有DOM和CSSOM来构架渲染树，这就有一个重要的影响：HTML和CSS都是阻塞渲染资源。<code>CSS是阻塞渲染的资源，需要将它尽早，尽快地下载到客户端，以便缩短首次渲染的时间。</code></p>

<p>但是，如果我们有一些CSS样式只在特定条件下使用，比如，页面答应，又或者页面投影到大屏幕上，我们期望页面不会受到这些样式的阻塞。</p>

<p>CSS媒体类型和媒体查询允许我们解决此类问题：</p>

<pre><code class="language-html">
&lt;link href=&quot;style.css&quot; rel=&quot;stylesheet&quot;&gt;
&lt;link href=&quot;print.css&quot; rel=&quot;stylesheet&quot; media=&quot;print&quot;&gt;
&lt;link href=&quot;other.css&quot; rel=&quot;stylesheet&quot; media=&quot;(min-width: 40em)&quot;&gt;

</code></pre>

<p>通过使用媒体查询，我们的外观可以根据不同使用场景定制，比如显示或打印，也可以根据不同情况比如屏幕方向改变、尺寸调整事件等定制。在声明样式表资源时，一定要多注意媒体类型和媒体查询，因为它们对关键渲染路径有极大的性能影响！</p>

<p>最后，请注意，「阻塞渲染」仅是指该资源是否会暂停浏览器的首次页面渲染。无论 CSS 是否阻塞渲染，CSS 资源都会被下载，只是说非阻塞性资源的优先级比较低而已。</p>

<h2 id="简化css选择符">简化CSS选择符</h2>

<p>针对CSS的性能的最佳实践：</p>

<ul>
<li>把样式表放在文档HEAD标签中以提升页面的逐步渲染速度。</li>
<li>不要在IE中使用CSS表达式，因为它们可能会被执行成千上万次，从而导致打开页面的速度变慢。</li>
<li>避免使用过多的行内样式，因为这会增加下载页面内容的大小。</li>
</ul>

<p>另外一个关键的问题就是CSS选择符的开销。选择符由一系列初始化的参数组成，这些参数指明了要应用这个CSS规则的网页元素。虽然遵循准则对CSS选择符进行优化可以提升网站速度，<strong>但更重要的是，Web开发者应该避免一些常见且开销很大的CSS选择符模式。</strong></p>

<h3 id="选择符的类型">选择符的类型</h3>

<p>以下按照最简单到最复杂的顺序列出（主要讨论性能，暂不作具体介绍）</p>

<ul>
<li>ID选择符</li>
<li>类选择符</li>
<li>类型选择符</li>
<li>相邻兄弟选择符</li>
<li>之选择符</li>
<li>后代选择符</li>
<li>通配符选择符</li>
<li>属性选择符</li>
<li>伪类和伪元素</li>
</ul>

<h3 id="高效css选择符的关键">高效CSS选择符的关键</h3>

<p>通过编写高效的选择符来控制匹配耗时，实现高效选择符之路是从理解选择符匹配开始的。</p>

<h4 id="最右边优先">最右边优先</h4>

<p>看如下规则：</p>

<p><code>#toc &gt; li { font-weight: bold; }</code></p>

<p>我们中大多数人，尤其是那些从左到右阅读的人，可能猜想浏览器执行也是从左到右匹配规则的，因此会推测这条规则的开销不高。</p>

<p><strong>事实上，CSS选择符是从右到左进行匹配的。</strong>了解这方面知识后，我们知道这个之前看似高效的规则实际上开销相当高，浏览器必须遍历页面上面每个<strong>li</strong>元素确定其夫元素的id是否为<strong>toc</strong></p>

<p>前面提到的后代选择符示例甚至更糟：</p>

<p><code>#toc A { color: #444; }</code></p>

<p>如果浏览器是从左到右读取的，那么它仅仅需要检查toc里的链接元素，实际上却检查了整个文档中的每个链接。然而，浏览器并不仅仅检查每个链接的父元素，还要遍历文档树去查找id为toc的祖先元素。如果被评估的链接不是toc的后代，那么浏览器就要向上一级遍历直到文档的根结点。</p>

<blockquote>
<p>样式系统从最右的选择符开始向左匹配规则。只要当前选择符的左边还有其他选择符，样式系统就会继续向左移动，直到找到和规则匹配的元素，或者因为不匹配而退出。</p>
</blockquote>

<h4 id="编写高效的css选择符">编写高效的CSS选择符</h4>

<p>编写高效选择符的指南：</p>

<p><strong>避免使用通配符规则</strong></p>

<p>除了传统意义上的通配选择符之外，Hyatt也把相邻兄弟选择符、子选择符、后代选择符和属性选择符归纳到“通配规则”分类下。他推荐仅使用ID、类和标签选择符。</p>

<p><strong>不要限定ID选择符</strong></p>

<p>在页面中一个指定的ID只能对应一个元素，所以没必要添加额外的限定符。例如，div＃toc是没有必要的，应该简化为＃toc。</p>

<p><strong>不要先定类选择符</strong></p>

<p>不要用具体的标签先定类选择符，而是根据实际情况对类名进行扩张。例如，把<code>li.chapter</code> 改成<code>.li-chapter</code>,或是<code>.list-chapter</code>更好。</p>

<p><strong>让规则越具体越好</strong></p>

<p>不要试图编写向<code>ol li a</code>这样的长选择符，最好是创建一个像<code>.list-anchor</code>一样的类，并把它添加到适当的元素上。</p>

<p><strong>避免使用后代选择符</strong></p>

<p>通常处理后代选择符的开销是最高的，而使用子选择符可以得到想要的结果，并且更高效。</p>

<p><strong>避免使用标签－－子选择符</strong></p>

<p>如果有像<code>#toc &gt; li &gt; a</code>这样的基于标签的子选择符，那么应该使用一个类来关联每个标签元素，如<code>.toc-achor</code></p>

<p><strong>质疑子选择符的所有用途</strong></p>

<p>再次提醒大家检查所有使用子选择符的地方，然而尽可能用具体的类取代它们。</p>

<p><strong>依靠继承</strong></p>

<p>了解哪些属性可以通过继承而来，然而避免对这些属性重复指定规则。例如，对列表元素而不是每个列表项元素指定<code>list-style-image</code>.请参考继承属性的列表来了解每个元素可继承的属性。</p>

<h3 id="css选择符性能">CSS选择符性能</h3>

<p>选择符从右到左读取的发现激发很多人重写规则。最重要的是首先评估该问题的影响力，这可以确保我们把注意力集中在正确的问题上。</p>

<h4 id="复杂的选择符影响性能-有时">复杂的选择符影响性能（有时）</h4>

<p>书中经过测试研究表明，像子选择符和后代选择符这样比较复杂的CSS选择符并不总是影响页面性能，但这并不意味着我们不需要优化CSS选择符。在平时编写CSS时，某些类型的选择符对性能还是会有显著的影响。</p>

<h4 id="应避免使用的css选择符">应避免使用的CSS选择符</h4>

<p>测试后代选择符的例子：</p>

<p><code>div div div p a.class0007 { ... }</code></p>

<p>初看之下，这似乎是一个匹配开销很高的选择符，它是一个要匹配五级祖先元素的后代选择符。然而，回想一下选择符是从右到左匹配的，我们就会认识到这个后代选择符执行的速度和一个更简单的类选择符差不多。最右边的参数也叫<strong>关键选择符</strong>，它对浏览器执行的工作量起主要影响。
在本例中，关键选择符就是<code>a.class0007</code>, 页面中自由一个元素匹配这个关键选择符，所以匹配这个选择符所需要的时间是极少的。</p>

<p>反之，看看这条规则：</p>

<p><code>a.class0007 * { ... }</code></p>

<p>在这条规则中，关键选择符是 <code>＊</code>。它匹配所有的元素，所以浏览器必须检查每个元素是否为类名为<code>class0007</code>的链接元素的后代。</p>

<p>当决定对哪儿进行优化时，记住将重心放在那些肯能匹配大量元素的<strong>关键选择符</strong>上。不仅通配选择有这个问题，下面几个例子同样会消耗大量的时间加载页面：</p>

<p><code>a.class0007 div { ... }</code>
<code>#id0007 div { ... }</code>
<code>.class0007 [href] { ... }</code>
<code>div:first-child { ... }</code></p>

<h4 id="回流时间-reflow-time">回流时间（reflow time）</h4>

<p>对于Web2.0应用来说，更应考虑当用户和网页交互时，浏览器应用样式和布局元素所花费的时间，这又叫做<strong>回流时间</strong>。</p>

<p>当使用JavaScript修改DOM元素样式的某些属性时会触发回流。对于这个叫elem的DOM元素，下面的每行代码在大多数浏览器中都会触发回流：</p>

<pre><code class="language-js">	elem.className = &quot;newclass&quot;;
	elem.style.cssText = &quot;color:red&quot;;
	elem.style.paddind = &quot;8px&quot;;
	elem.style.display = &quot;&quot;;
</code></pre>

<p>这仅仅是一个子集，能触发回流的列表太长了。回流并不需要设计页面上的所有元素，浏览器已为此进行了优化，仅仅只对那些受回流影响的元素重新布局。如果elem是文档的body或其他一些有很多后代的元素，那么回流的开销一定相当高。</p>

<p>回流需要从新应用CSS规则，这意味着浏览器必须再次匹配所有的CSS选择符。如果CSS选择符是低效的，那么回流可能消耗的时间就会多到引起用户注意。</p>

<p>因此，对于杜绝低效CSS选择符的影响，不仅要考虑页面加载时间，也要考虑用户和Web2.0应用交互时如何使用样式进行表现，这一点非常重要。如果JavaScript对样式属性有操作，且网页开始变慢，那么低效的CSS选择符就很可能是罪魁祸首。</p>

<p>编写高效的CSS选择符是要付出成本的：将每个受影响元素的后代选择符替换成类选择符，不仅会增加页面大小，还会降低样式的灵活性。
最需要修正的选择符是那些可以匹配大量元素的关键选择符（最右边的选择符）。虽然性能提升的益处多种多样，但Web开发者应该避免使用会影响网页性能的CSS选择符。</p>

<h2 id="自动化工具">自动化工具</h2>

<p><strong>uncss</strong></p>

<p>从css文件中移除掉无用的css样式。
我们在写开发css样式的过程中，由于版本迭代，代码重构，编写习惯等的原因，样式表中常常会出现很多无用的css样式。
另一方面，在我们引入的外部css样式库中，也会有很多我们不需要的css样式。
当你去做这些检查的时候，结果往往会让你吃惊，竟然会有那么多样式没有使用到。增加下载量，引起浏览器不必要的加载和下载量。</p>

<p>这个时候使用<strong>uncss</strong>变的很有必要。</p>

<p>安装：</p>

<p><code>npm install -g uncss</code></p>

<p>Demo：</p>

<pre><code class="language-js">
var uncss = require('uncss');

var files   = ['my', 'array', 'of', 'HTML', 'files', 'or', 'http://urls.com'],
    options = {
        ignore       : ['#added_at_runtime', /test\-[0-9]+/],
        media        : ['(min-width: 700px) handheld and (orientation: landscape)'],
        csspath      : '../public/css/',
        raw          : 'h1 { color: green }',
        stylesheets  : ['lib/bootstrap/dist/css/bootstrap.css', 'src/public/css/main.css'],
        ignoreSheets : [/fonts.googleapis/],
        timeout      : 1000,
        htmlroot     : 'public',
        report       : false,
        uncssrc      : '.uncssrc'
    };

uncss(files, options, function (error, output) {
    console.log(output);
});

/* Look Ma, no options! */
uncss(files, function (error, output) {
    console.log(output);
});

/* Specifying raw HTML */
var rawHtml = '...';

uncss(rawHtml, options, function (error, output) {
    console.log(output);
});
</code></pre>

<p>同样可以使用gulp自动编译：</p>

<p><code>npm install gulp-uncss --save-dev</code></p>

<pre><code class="language-js">var gulp = require('gulp');
var uncss = require('gulp-uncss');

gulp.task('default', function () {
    return gulp.src('site.css')
        .pipe(uncss({
            html: ['index.html', 'posts/**/*.html', 'http://example.com']
        }))
        .pipe(gulp.dest('./dist'));
});
</code></pre>

<p>Notes:</p>

<p>使用<code>uncss</code>有个问题就是，代码中如果有懒加载，延迟加载，依赖加载的部分，uncss同样会做删除，所以这部分代码还得用户自行添加，个人建议将这些代码保存在一个文件下，通过设置uncss参数过滤掉这个文件即可。</p>

<p><strong>nano</strong></p>

<p>cssnano是一个模块化的minifier，旨在利用PostCSS生态系统中的小模块，而不是一个可能很难贡献的全面模块。因为它是写在PostCSS的顶部，它能够做更多比简单的空白变换 - 包括高级优化，如自定义标识符减少，z-index,rebasing和相邻选择器合并。</p>

<p>cssnano默认启用积极的优化，这可能不总是你想要的。如果要禁用此选项，请将options.safe设置为true。在以后的版本中，默认情况下仅启用安全选项，从版本4开始.</p>

<p>结合上面的代码可以使用：</p>

<pre><code class="language-js">
var gulp = require('gulp');
var uncss = require('gulp-uncss');
var cssnano = require('cssnano');

gulp.task('default', function () {
    return gulp.src('site.css')
        .pipe(uncss({
            html: ['index.html', 'posts/**/*.html', 'http://example.com']
        }))
        .pipe(cssnano())
        .pipe(gulp.dest('./dist'));
});
</code></pre>

<p><strong>Autoprefixer</strong></p>

<p>PostCSS插件来解析CSS，并使用<code>CanIUse</code>的值将供应商前缀添加到CSS规则。</p>

<p>e.g.</p>

<pre><code class="language-css">:fullscreen a {
    display: flex
}
</code></pre>

<p>上面的css代码会被编译成如下的形式：</p>

<pre><code class="language-css">:-webkit-full-screen a {
    display: -webkit-box;
    display: flex
}
:-moz-full-screen a {
    display: flex
}
:-ms-fullscreen a {
    display: -ms-flexbox;
    display: flex
}
:fullscreen a {
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex
}
</code></pre>

<p>结合gulp使用方法：</p>

<pre><code class="language-js">var postcss = require('gulp-postcss');
var autoprefixer = require('autoprefixer');

gulp.src(['src/style/**.scss'])
        .pipe(sass())
        .pipe(minifyCss({compatibility: 'ie8'}))
        .pipe(postcss([autoprefixer({browsers: ['last 2 versions']})]))
        .pipe(cssnano())
        .pipe(sourcemaps.write('.'))
        .pipe(gulp.dest('dist/style'))
</code></pre>

<p><strong>gulp-cssmin</strong></p>

<p>对css进行压缩。</p>

<p><code>npm install --save-dev gulp-cssmin</code></p>

<pre><code class="language-js">var gulp = require('gulp');
var cssmin = require('gulp-cssmin');
var rename = require('gulp-rename');

gulp.task('default', function () {
    gulp.src('src/**/*.css')
        .pipe(cssmin())
        .pipe(rename({suffix: '.min'}))
        .pipe(gulp.dest('dist'));
});
</code></pre>

<p>更多的<a href="https://github.com/jakubpawlowicz/clean-css">选线设置</a></p>

  </div>
</div>
<div class="container has-text-centered">
    
</div>

<div class="container has-text-centered">
  
</div>
<section class="section">
  <div class="container has-text-centered">
    <p></p>
  </div>
</section>


